package com.wish233.server.impl;

import com.wish233.model.protocol.NetServerBufferHandlerWrapper;
import com.wish233.model.protocol.ProtocolDecoder;
import com.wish233.model.protocol.ProtocolEncoder;
import com.wish233.model.protocol.WishProtocol;
import com.wish233.model.protocol.enums.ProtocolMessageTypeEnum;
import com.wish233.model.rpc.RpcRequest;
import com.wish233.model.rpc.RpcResponse;
import com.wish233.register.local.LocalServiceRegister;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetSocket;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author WHH
 * 请求处理器
 */
@Slf4j
public class NetServerHandler implements Handler<NetSocket> {

    /**
     * 提供请求，反射调用服务提供者
     *
     * @param netSocket
     */
    @Override
    public void handle(NetSocket netSocket) {
        NetServerBufferHandlerWrapper wrapper = new NetServerBufferHandlerWrapper(buffer -> {
            //获取请求
            WishProtocol<RpcRequest> request;
            try {
                //解码
                request = (WishProtocol<RpcRequest>) ProtocolDecoder.decode(buffer);
            } catch (IOException e) {
                throw new RuntimeException("解码错误！", e);
            }
            RpcRequest body = request.getBody();
            RpcResponse response = new RpcResponse();
            //获取服务的调用类
            Class<?> service = LocalServiceRegister.getService(body.getServiceName());
            try {
                //执行方法
                Method method = service.getMethod(body.getMethodName(), body.getParameterTypes());
                Object result = method.invoke(service.getDeclaredConstructor().newInstance(), body.getArgs());
                //封装结果
                response.setData(result);
                response.setDataType(method.getReturnType());
            } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException |
                     InstantiationException e) {
                response.setMessage(e.getMessage());
                response.setException(e);
            }
            //编码并发送响应
            WishProtocol.Header header = request.getHeader();
            header.setType((byte) ProtocolMessageTypeEnum.RESPONSE.getKey());
            WishProtocol<RpcResponse> responseWishProtocol = new WishProtocol<>(header, response);
            try {
                Buffer encode = ProtocolEncoder.encode(responseWishProtocol);
                netSocket.write(encode);
            } catch (IOException e) {
                throw new RuntimeException("解码错误！", e);
            }
        });
        netSocket.handler(wrapper);
    }
}
